﻿using System.Collections.ObjectModel;
using System.ComponentModel;

namespace Effector.ViewModel
{
    /// <summary>
    /// Base class for the view model implementing the INotifyPropertyChanged interface.
    /// </summary>
    public class FileSystemElementModel : INotifyPropertyChanged
    {
        static readonly FileSystemElementModel _dummy = new FileSystemElementModel();

        private ObservableCollection<FileSystemElementModel> _children;
        
        private FileSystemElementModel _parent;

        bool _isExpanded;
        
        /// <summary>
        /// Gets or sets a value indicating whether this instance is expanded.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is expanded; otherwise, <c>false</c>.
        /// </value>
        /// <remarks>
        /// This is data binded to the controls's same property in two way.So any of the 2 changes
        /// the other changes too.
        /// </remarks>
        public bool IsExpanded
        {
            get { return _isExpanded; }
            set
            {
                if (value != _isExpanded)
                {
                    _isExpanded = value;
                    this.OnPropertyChanged("IsExpanded");
                }

                // Expand all the way up to the root.
                if (_isExpanded && _parent != null)
                    _parent.IsExpanded = true;

                // Lazy load the child items, if necessary.
                if (this._children.Count == 1 && this._children[0] == _dummy)
                {
                    this.Children.Clear();
                    this.LoadChildren();
                }
            }
        }

        /// <summary>
        /// Gets the children.
        /// </summary>
        /// <value>The children.</value>
        public ObservableCollection<FileSystemElementModel> Children
        {
            get { return _children; }
        }

        /// <summary>
        /// Gets the parent.
        /// </summary>
        /// <value>The parent.</value>
        public FileSystemElementModel Parent
        {
            get { return _parent; }
        }

        /// <summary>
        /// Loads the children.
        /// </summary>
        protected virtual void LoadChildren()
        {
        }

        /// <summary>
        /// Gets the selected.
        /// </summary>
        /// <param name="selectedvalue">The selectedvalue.</param>
        public virtual void GetSelected(out string selectedvalue)
        {
            selectedvalue = string.Empty;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="FileSystemElementModel"/> class.
        /// </summary>
        /// <param name="parent">The parent.</param>
        protected FileSystemElementModel(FileSystemElementModel parent)
        {
            _parent = parent;

            _children = new ObservableCollection<FileSystemElementModel>();
            _children.Add(_dummy);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="FileSystemElementModel"/> class.
        /// </summary>
        private FileSystemElementModel()
        {
        }

        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Called when [property changed].
        /// </summary>
        /// <param name="propertyName">Name of the property.</param>
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
